package model

import (
	"fmt"
	"go-devops/domain/dto"
	"os"
	"path/filepath"
	"sync"
)

type SseClientMap struct {
	lock      sync.RWMutex
	clientMap map[string]*SseStream
}

func NewSseClientMap() *SseClientMap {
	return &SseClientMap{
		clientMap: make(map[string]*SseStream),
	}
}

func (s *SseClientMap) Set(key string, value *SseStream) {
	s.lock.Lock()
	defer s.lock.Unlock()
	s.clientMap[key] = value
}

func (s *SseClientMap) Get(key string) (value *SseStream) {
	s.lock.RLock()
	defer s.lock.RUnlock()
	value, _ = s.clientMap[key]
	return value
}

func (s *SseClientMap) Delete(key string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	delete(s.clientMap, key)
}

type TaskConnMap struct {
	lock    sync.RWMutex
	taskMap map[string]*SseClientMap
}

func NewTaskConnMap() *TaskConnMap {
	return &TaskConnMap{
		taskMap: make(map[string]*SseClientMap),
	}
}

func (s *TaskConnMap) Set(key string, value *SseClientMap) {
	s.lock.Lock()
	defer s.lock.Unlock()
	s.taskMap[key] = value
}

func (s *TaskConnMap) Get(key string) (value *SseClientMap) {
	s.lock.RLock()
	defer s.lock.RUnlock()
	value, _ = s.taskMap[key]
	return value
}

func (s *TaskConnMap) Delete(key string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	delete(s.taskMap, key)
}

func (s *TaskConnMap) Send(nodeContext *dto.NodeContext, msgData *MsgData) {
	s.lock.RLock()
	taskId := nodeContext.TaskId
	clientMap := s.taskMap[taskId]
	if clientMap == nil {
		return
	}

	for _, stream := range clientMap.clientMap {
		event := SseEvent{
			Data: msgData,
		}
		stream.Send(event)
	}
	saveLog(nodeContext, msgData)
	s.lock.RUnlock()
}

func saveLog(nodeContext *dto.NodeContext, msgData *MsgData) {
	if FLOW == msgData.MsgType || NODE == msgData.MsgType {
		return
	}

	if len(msgData.Msg) <= 0 {
		return
	}

	os.MkdirAll(filepath.Join(nodeContext.Workspace, "log"), os.ModePerm)
	file, err := os.OpenFile(nodeContext.LogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		return
	}
	defer file.Close()

	file.WriteString(fmt.Sprintf("%s %s\n", msgData.Time, msgData.Msg))
}
